﻿using SuperMap.Data;
using SuperMap.UI;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Ycjw.PipeLine.Map.Basic.SuperMap;

namespace Ycjw.PipeLine.Scenes
{
    /****************************************************************************************/
    /*
    功    能:放置三维场景的DocWindow
    作    者: RenZachary
    联系方式: rzcgis@foxmail.com（QQ455745253）
    生成日期: 2021年3月24日
    修改日志: 
    版权说明: @2021 西安云创经纬信息科技有限公司 版权所有 All right reserved.
    注    意: 本内容仅限于云创经纬公司内部使用，禁止用于商业目的。
    */
    /****************************************************************************************/
    class SceneMeasure : SceneOperInterface
    {
        private readonly FormMainRibbon m_FormMainRibbon;
        public SceneControl SceneControl
        {
            get
            {
                return m_SceneControl;
            }
            set
            {
                if(value != SceneControl)
                    SceneControl = value;
            }
        }

        //// 定义存储字符串的变量
        //// Define a variable to store strings
        //private readonly String m_meter = "米";
        //private readonly String m_squareMeter = "平方米";
        //private readonly String m_length = "长度：";
        //private readonly String m_area = "面积：";
        //private readonly String m_height = "高度：";

        //private String m_MessageTag = "MeasureAltitude";

        private Point3Ds m_Point3Ds;
        private Double m_CurLength = 0.0;
        private Double m_CurAltitude = 0.0;
        private GeoText3D m_currentGeoText3DMessage;
        private String m_StrResult;
        private Point3D m_TempPoint;

        private static String m_messageTag = "MeasureDistancePart";
        private static String m_messageTrackingTag = "MeasureDistanceTracking";
        private static String m_MeasureDistanceTag = "MeasureDistance";
        private static String m_MeasureAreaTag = "MeasureArea";
        private static String m_MeasureAltitudeTag = "MeasureAltitude";
        private GeoStyle3D m_GeoStyle3DTemp;
        private GeoStyle3D m_GeoStyle3D;
        public override void UnRegister()
        {
            m_UnRegistered = true;
        }
        /// <summary>
        /// 根据sceneControl构造 SampleRun对象
        /// Initialize the SampleRun object with the specified sceneControl.
        /// </summary>
        public SceneMeasure(SceneControl sceneControl, FormMainRibbon formMain) : base(sceneControl,formMain)
        {
            try
            {
                m_SceneControl = sceneControl;
                m_FormMainRibbon = formMain;

                m_FormMainRibbon.ribbonButtonAltitude.Click += RibbonButtonAltitude_Click;
                m_FormMainRibbon.ribbonButtonClear.Click += RibbonButtonClear_Click;
                m_FormMainRibbon.ribbonButtonMeasureArea.Click += RibbonButtonMeasureArea_Click;
                m_FormMainRibbon.ribbonButtonMeasureDistance.Click += RibbonButtonMeasureDistance_Click;
                m_FormMainRibbon.ribbonButtonMeasureHorizotalDistance.Click += RibbonButtonMeasureHorizotalDistance_Click;
                m_FormMainRibbon.ribbonButtonMeasureTerrainArea.Click += RibbonButtonMeasureTerrainArea_Click;
                m_FormMainRibbon.ribbonButtonMeasureTerrainDistance.Click += RibbonButtonMeasureTerrainDistance_Click;
                m_FormMainRibbon.ribbonButtonStopMeasure.Click += RibbonButtonStopMeasure_Click;

                Initialize();
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        private void RibbonButtonStopMeasure_Click(object sender, EventArgs e)
        {
            m_SceneControl.Action = Action3D.Pan;
            m_UnRegistered = true;
        }

        private void RibbonButtonMeasureTerrainDistance_Click(object sender, EventArgs e)
        {
            BeginMeasureTerrainDistance();
            m_UnRegistered = false;
        }

        private void RibbonButtonMeasureTerrainArea_Click(object sender, EventArgs e)
        {
            BeginMeasureTerrainArea();
            m_UnRegistered = false;
        }

        private void RibbonButtonMeasureHorizotalDistance_Click(object sender, EventArgs e)
        {
            BeginMeasureHorizontalDistance();
            m_UnRegistered = false;
        }

        private void RibbonButtonMeasureDistance_Click(object sender, EventArgs e)
        {
            BeginMeasureDistance();
            m_UnRegistered = false;
        }

        private void RibbonButtonMeasureArea_Click(object sender, EventArgs e)
        {
            BeginMeasureArea();
            m_UnRegistered = false;
        }

        private void RibbonButtonClear_Click(object sender, EventArgs e)
        {
            ClearResult();
            m_UnRegistered = true;
        }

        private void RibbonButtonAltitude_Click(object sender, EventArgs e)
        {
            BeginMeasureAltitude();
            m_UnRegistered = false;
        }

        private GeoText3D CreateText3DMessage()
        {
            TextPart3D textPart3D = new TextPart3D
            {
                AnchorPoint = new Point3D(0, 0, 0),
                Text = String.Empty
            };

            TextStyle style = new TextStyle
            {
                ForeColor = Color.White,
                IsSizeFixed = true,
                FontHeight = 4
            };
            GeoText3D text3D = new GeoText3D(textPart3D, style)
            {
                Style3D = new GeoStyle3D()
            };
            text3D.Style3D.AltitudeMode = AltitudeMode.RelativeToGround;
            return text3D;
        }

        /// <summary>
        /// 打开需要的地形文件和影像文件
        /// Open the terrain file and image file
        /// </summary>
        private void Initialize()
        {
            try
            {
                // 调整sceneControl的状态
                // Adjust the status of sceneControl
                m_SceneControl.Action = Action3D.Pan;

                // 注册事件
                // Register the event
                m_SceneControl.Tracking += new Tracking3DEventHandler(TrackingHandler);
                m_SceneControl.Tracked += new Tracked3DEventHandler(TrackedHandler);
                m_SceneControl.MouseUp += SceneControl_MouseUp;

                m_Point3Ds = new Point3Ds();

                m_GeoStyle3D = new GeoStyle3D
                {
                    MarkerColor = Color.FromArgb(255, 0, 255),
                    LineColor = Color.FromArgb(255, 255, 0),
                    LineWidth = 1,
                    FillForeColor = Color.FromArgb(180, Color.Violet),
                    AltitudeMode = AltitudeMode.ClampToGround
                };

                m_GeoStyle3DTemp = new GeoStyle3D
                {
                    MarkerColor = Color.FromArgb(255, 0, 0),
                    LineColor = Color.FromArgb(0, 255, 0),
                    LineWidth = 1,
                    FillForeColor = Color.FromArgb(180, Color.Violet),
                    AltitudeMode = AltitudeMode.ClampToGround
                };

            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        // 量算结束
        // End of the measurement
        private void EndOneMeasure()
        {
            try
            {
                m_CurLength = 0.0;
                m_CurAltitude = 0.0;
                m_Point3Ds.Clear();
                m_TempPoint = Point3D.Empty;
                m_StrResult = String.Empty;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
        }

        // 鼠标右键，负责 显示分段量算结果
        // The right mouse button shows the segmentation results
        void SceneControl_MouseUp(object sender, MouseEventArgs e)
        {
            if (m_UnRegistered) return;
            if (e.Button == MouseButtons.Right)
            {
                EndOneMeasure();
            }

            if (e.Button == MouseButtons.Left)
            {
                if (m_Point3Ds.Count == 0)
                {
                    //ClearMeasureResult();
                }

                if (m_TempPoint != Point3D.Empty && m_Point3Ds.Count > 1)
                {
                    m_Point3Ds.Remove(m_Point3Ds.Count - 1);
                    m_TempPoint = Point3D.Empty;
                }

                Point3D point3D;
                if (m_SceneControl.Action == Action3D.MeasureDistance
                    || m_SceneControl.Action == Action3D.MeasureAltitude || m_SceneControl.Action == Action3D.MeasureHorizontalDistance)
                {
                    point3D = m_SceneControl.Scene.PixelToGlobe(new Point(e.X, e.Y), SuperMap.Realspace.PixelToGlobeMode.TerrainAndModel);
                }
                else
                {
                    point3D = m_SceneControl.Scene.PixelToGlobe(new Point(e.X, e.Y));
                }

                if (!Double.IsNaN(point3D.X) && !Double.IsNaN(point3D.Y) && !Double.IsNaN(point3D.Z))
                {
                    m_Point3Ds.Add(point3D);
                    if (m_SceneControl.Action == Action3D.MeasureHorizontalDistance || m_SceneControl.Action == Action3D.MeasureDistance)
                    {
                        // 添加部分段长度
                        // Add part length 
                        if (!Toolkit.IsZero(m_CurLength))
                        {
                            if (m_Point3Ds.Count >= 2)
                            {
                                m_Point3Ds.RemoveRange(0, m_Point3Ds.Count - 2);
                                String distanceUnit = "米";
                                if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                                {
                                    distanceUnit = "Meters";
                                }
                                GeoLine3D geoLine3D = new GeoLine3D(m_Point3Ds);
                                TextPart3D textPart3D = new TextPart3D
                                {
                                    AnchorPoint = new Point3D(0, 0, 0)
                                };
                                Double tempCurLength = m_CurLength;
                                textPart3D.Text = String.Format("{0:F2}{1}", tempCurLength, " " + distanceUnit);
                                if (m_Point3Ds[0].X > 0 && m_Point3Ds[1].X > 0 ||
                                    m_Point3Ds[0].X < 0 && m_Point3Ds[1].X < 0)
                                {
                                    textPart3D.X = geoLine3D.InnerPoint3D.X;
                                }
                                else
                                {
                                    textPart3D.X = 180;
                                }

                                textPart3D.Y = geoLine3D.InnerPoint3D.Y;
                                textPart3D.Z = geoLine3D.InnerPoint3D.Z;

                                GeoText3D text3d = m_currentGeoText3DMessage ?? GetGeoText3DMessage();
                                text3d.AddPart(textPart3D);

                                text3d.TextStyle.FontHeight = 6;
                                text3d.TextStyle.Alignment = TextAlignment.BottomLeft;
                                text3d.TextStyle.BackColor = Color.Black;
                                text3d.TextStyle.Outline = true;
                                text3d.Style3D.AltitudeMode = AltitudeMode.Absolute;

                                int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTag);
                                if (index >= 0)
                                {
                                    m_SceneControl.Scene.TrackingLayer.Remove(index);
                                }
                                //ClearTextMessageTag();
                                m_SceneControl.Scene.TrackingLayer.Add(text3d, m_messageTag);
                            }
                        }

                        else if (m_SceneControl.Action == Action3D.MeasureTerrainDistance)
                        {
                            // 添加部分段长度
                            // Add part length 
                            if (!Toolkit.IsZero(m_CurLength))
                            {
                                if (m_Point3Ds.Count >= 2)
                                {
                                    m_Point3Ds.RemoveRange(0, m_Point3Ds.Count - 2);

                                    GeoLine3D geoLine3D = new GeoLine3D(m_Point3Ds);
                                    String distanceUnit = "米";
                                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                                    {
                                        distanceUnit = "Meters";
                                    }
                                    TextPart3D textPart3D = new TextPart3D
                                    {
                                        AnchorPoint = new Point3D(0, 0, 0)
                                    };
                                    Double tempCurLength = m_CurLength;
                                    textPart3D.Text = String.Format("{0:F2}{1}", tempCurLength, " " + distanceUnit);
                                    if (m_Point3Ds[0].X > 0 && m_Point3Ds[1].X > 0 ||
                                        m_Point3Ds[0].X < 0 && m_Point3Ds[1].X < 0)
                                    {
                                        textPart3D.X = geoLine3D.InnerPoint.X;
                                        textPart3D.Y = geoLine3D.InnerPoint.Y;
                                    }
                                    else
                                    {
                                        textPart3D.X = 180;
                                        textPart3D.Y = geoLine3D.InnerPoint.Y;
                                    }
                                    textPart3D.Z = 0;
                                    GeoText3D text3d = GetGeoText3DMessage();
                                    text3d.AddPart(textPart3D);
                                    text3d.TextStyle.FontHeight = 6;
                                    text3d.TextStyle.Alignment = TextAlignment.BottomLeft;
                                    text3d.TextStyle.BackColor = Color.Black;
                                    text3d.TextStyle.Outline = true;
                                    text3d.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                                    ClearTextMessageTag();
                                    m_SceneControl.Scene.TrackingLayer.Add(text3d, m_messageTag);
                                }
                            }
                        }
                        else if (m_SceneControl.Action == Action3D.MeasureArea)
                        {

                        }
                        else if (m_SceneControl.Action == Action3D.MeasureAltitude)
                        {
                            //清除量算高度信息
                            // Clear height information
                            if (!(Toolkit.IsZero(m_CurAltitude)))
                            {
                                EndOneMeasure();
                            }
                        }

                    }
                }
            }
        }

        private void ClearTextMessageTag()
        {
            int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTag);
            while (index >= 0)
            {
                m_SceneControl.Scene.TrackingLayer.Remove(index);
                index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTag);
            }
            m_currentGeoText3DMessage = null;
        }

        private GeoText3D GetGeoText3DMessage()
        {
            GeoText3D text = CreateText3DMessage();
            m_SceneControl.Scene.TrackingLayer.Add(text, m_messageTag);
            m_currentGeoText3DMessage = text;
            return text;
        }

        /// <summary>
        /// 显示最终量算的结果
        /// Display the result of the measure
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void TrackedHandler(object sender, Tracked3DEventArgs e)
        {
            if (m_UnRegistered) return;
            try
            {
                // 清空临时结果
                // Clear provisional results
                m_Point3Ds.Clear();
                m_CurLength = 0.0;

                Geometry3D geometry = e.Geometry;
                if (geometry == null) return;
                Point3D textLocation = new Point3D(0, 0, 0);

                String text = String.Empty;
                if (m_SceneControl.Action == Action3D.MeasureDistance || m_SceneControl.Action == Action3D.MeasureTerrainDistance)
                {
                    // 绘制量算线对象
                    // Draw a line object
                    GeoLine3D geoLine3D = e.Geometry.Clone() as GeoLine3D;
                    geoLine3D.Style3D = m_GeoStyle3D.Clone();
                    if (m_SceneControl.Action == Action3D.MeasureDistance)
                    {
                        geoLine3D.Style3D.AltitudeMode = AltitudeMode.Absolute;
                    }
                    else
                    {
                        geoLine3D.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                    }
                    m_SceneControl.Scene.TrackingLayer.Add(geoLine3D, m_MeasureDistanceTag);

                    // 绘制量算点对象
                    // Draw a point object
                    Point3D point3D = Point3D.Empty;
                    for (Int32 i = 0; i < geoLine3D.PartCount; i++)
                    {
                        for (Int32 j = 0; j < geoLine3D[i].Count; j++)
                        {
                            GeoPoint3D geoPoint3D = new GeoPoint3D(geoLine3D[i][j])
                            {
                                Style3D = m_GeoStyle3D.Clone()
                            };
                            if (m_SceneControl.Action == Action3D.MeasureDistance)
                            {
                                geoPoint3D.Style3D.AltitudeMode = AltitudeMode.Absolute;
                            }
                            else if (m_SceneControl.Action == Action3D.MeasureTerrainDistance)
                            {
                                geoPoint3D.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                            }
                            m_SceneControl.Scene.TrackingLayer.Add(geoPoint3D, m_MeasureDistanceTag);
                            point3D = geoLine3D[i][j];
                        }
                    }

                    // 量算结果
                    // result
                    int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTrackingTag);
                    if (index >= 0)
                    {
                        m_SceneControl.Scene.TrackingLayer.Remove(index);
                    }

                    // 添加结果文字
                    // Add a result description
                    if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                    {
                        if (m_SceneControl.Action == Action3D.MeasureDistance)
                        {
                            text = String.Format("{0}{1}{2}", "空间距离：", Math.Round(Convert.ToDecimal(e.Length), 2), "米");
                        }
                        else
                        {
                            text = String.Format("{0}{1}{2}", "依地距离：", Math.Round(Convert.ToDecimal(e.Length), 2), "米");
                        }
                    }
                    else
                    {
                        if (m_SceneControl.Action == Action3D.MeasureDistance)
                        {
                            text = String.Format("{0}{1}{2}", "SpaceDistance：", Math.Round(Convert.ToDecimal(e.Length), 2), "Meters");
                        }
                        else
                        {
                            text = String.Format("{0}{1}{2}", "TerrainDistance：", Math.Round(Convert.ToDecimal(e.Length), 2), "Meters");
                        }
                    }

                    textLocation = geoLine3D[0][geoLine3D[0].Count - 1];
                    GeoText3D geoText = new GeoText3D(new TextPart3D(text, textLocation));
                    SetResultTextStyle(geoText);
                    m_SceneControl.Scene.TrackingLayer.Add(geoText, "MeasureDistance");

                    // 计算首尾点高度差
                    // Calulate the head and tall height difference
                    Point3Ds point3Ds = geoLine3D[0];
                    double height = point3Ds[point3Ds.Count - 1].Z - point3Ds[0].Z;

                    m_FormMainRibbon.ShowInfo(text);
                    String message = "";
                    if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                    {
                        message = string.Format("首尾点高度差为:{0}米。", height.ToString("##.00"));
                    }
                    else
                    {
                        message = string.Format("The head and tall height difference is:{0}Meters。", height.ToString("##.00"));
                    }
                    m_FormMainRibbon.ShowInfo(message);
                }

                else if (m_SceneControl.Action == Action3D.MeasureArea || m_SceneControl.Action == Action3D.MeasureTerrainArea)
                {
                    // 绘制量算面对象
                    // Draw a region object
                    GeoRegion3D geoRegion3D = e.Geometry as GeoRegion3D;
                    geoRegion3D.Style3D = m_GeoStyle3D.Clone();
                    if (m_SceneControl.Action == Action3D.MeasureArea)
                    {
                        geoRegion3D.Style3D.AltitudeMode = AltitudeMode.Absolute;
                    }
                    else
                    {
                        geoRegion3D.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                    }
                    geoRegion3D.Style3D.FillForeColor = Color.FromArgb(120, 250, 250, 50);
                    ClearTextMessageTag();
                    int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTrackingTag);
                    if (index >= 0)
                    {
                        m_SceneControl.Scene.TrackingLayer.Remove(index);
                    }
                    m_SceneControl.Scene.TrackingLayer.Add(geoRegion3D, "geoRegion3D");

                    // 绘制量算点对象
                    // Draw a point object
                    for (Int32 i = 0; i < geoRegion3D.PartCount; i++)
                    {
                        for (Int32 j = 0; j < geoRegion3D[i].Count; j++)
                        {
                            GeoPoint3D geoPoint3D = new GeoPoint3D(geoRegion3D[i][j])
                            {
                                Style3D = m_GeoStyle3D.Clone()
                            };
                            if (m_SceneControl.Action == Action3D.MeasureArea)
                            {
                                geoPoint3D.Style3D.AltitudeMode = AltitudeMode.Absolute;
                            }
                            else if (m_SceneControl.Action == Action3D.MeasureTerrainArea)
                            {
                                geoPoint3D.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                            }
                            m_SceneControl.Scene.TrackingLayer.Add(geoPoint3D, m_MeasureAreaTag + i.ToString() + j.ToString());
                        }
                    }

                    ClearTextMessageTag();

                    // 量算结果
                    // result
                    if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                    {
                        if (m_SceneControl.Action == Action3D.MeasureArea)
                        {
                            m_StrResult = String.Format("{0}{1}{2}", "空间面积：", Math.Round(Convert.ToDecimal(e.Area), 2), "平方米");
                        }
                        else
                        {
                            m_StrResult = String.Format("{0}{1}{2}", "依地面积：", Math.Round(Convert.ToDecimal(e.Area), 2), "平方米");
                        }
                    }
                    else
                    {
                        if (m_SceneControl.Action == Action3D.MeasureArea)
                        {
                            m_StrResult = String.Format("{0}{1}{2}", "SapceArea：", Math.Round(Convert.ToDecimal(e.Area), 2), "Square Meters");
                        }
                        else
                        {
                            m_StrResult = String.Format("{0}{1}{2}", "TerrainArea：", Math.Round(Convert.ToDecimal(e.Area), 2), "Square Meters");
                        }
                    }
                    GeoText3D text3d = GetGeoText3DMessage();
                    text3d[0].Text = m_StrResult;
                    text3d[0].X = geoRegion3D.InnerPoint3D.X;
                    text3d[0].Y = geoRegion3D.InnerPoint3D.Y;
                    text3d[0].Z = geoRegion3D.InnerPoint3D.Z;

                    GeoText3D geoText = new GeoText3D(text3d);
                    // 添加结果文字
                    // Add a result description
                    SetResultTextStyle(geoText);
                    m_SceneControl.Scene.TrackingLayer.Add(geoText, "MeasureArea");

                    m_FormMainRibbon.ShowInfo(m_StrResult);
                }

                else if (m_SceneControl.Action == Action3D.MeasureAltitude)
                {
                    //绘制量算线对象
                    if (!(e.Geometry is GeoLine3D geoLine3D)) return;
                    geoLine3D.Style3D = m_GeoStyle3D.Clone();
                    geoLine3D.Style3D.AltitudeMode = AltitudeMode.Absolute;
                    m_SceneControl.Scene.TrackingLayer.Add(geoLine3D, "Altitude");
                    // 添加结果文字
                    // Add a result description
                    if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                    {
                        text = String.Format("{0}{1}{2}", "高度：", Math.Round(Convert.ToDecimal(e.Height), 2), "米");

                    }
                    else
                    {
                        text = String.Format("{0}{1}{2}", "Height：", Math.Round(Convert.ToDecimal(e.Height), 2), "Meters");
                    }
                    textLocation = geoLine3D[0][geoLine3D[0].Count - 1];
                    GeoText3D geoText = new GeoText3D(new TextPart3D(text, textLocation));
                    SetResultTextStyle(geoText);
                    m_SceneControl.Scene.TrackingLayer.Add(geoText, "Altitude");

                    // 输出首尾点高度
                    // Output the head and tall height
                    Point3Ds point3Ds = geoLine3D[0];
                    double startHeight = point3Ds[0].Z;
                    double endHeight = point3Ds[1].Z;
                    string message = "";
                    message = string.Format("首点高度为:{0}米。", startHeight.ToString("##.00"));
                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                    {
                        message = string.Format("The head height difference is:{0}Meters。", startHeight.ToString("##.00"));
                    }
                    m_FormMainRibbon.ShowInfo(message);
                    message = string.Format("尾点高度为:{0}米。", endHeight.ToString("##.00"));
                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                    {
                        message = string.Format("The tall height difference is:{0}Meters。", startHeight.ToString("##.00"));
                    }
                    m_FormMainRibbon.ShowInfo(message);

                    // 绘制量算点对象
                    // Draw a point object
                    for (Int32 i = 0; i < geoLine3D.PartCount; i++)
                    {
                        for (Int32 j = 0; j < geoLine3D[i].Count; j++)
                        {
                            GeoPoint3D geoPoint3D = new GeoPoint3D(geoLine3D[i][j])
                            {
                                Style3D = m_GeoStyle3D.Clone()
                            };
                            geoPoint3D.Style3D.AltitudeMode = AltitudeMode.Absolute;
                            m_SceneControl.Scene.TrackingLayer.Add(geoPoint3D, m_MeasureAltitudeTag + j.ToString());
                        }
                    }
                    ClearTextMessageTag();
                    if (!(Toolkit.IsZero(m_CurAltitude)))
                    {
                        EndOneMeasure();
                    }
                }

                else if (m_SceneControl.Action == Action3D.MeasureHorizontalDistance)
                {
                    // 结果线
                    // Results the line 
                    GeoLine3D resLine3D = e.Geometry as GeoLine3D;
                    resLine3D.Style3D = m_GeoStyle3D.Clone();
                    resLine3D.Style3D.AltitudeMode = AltitudeMode.Absolute;


                    // 结果点
                    // Results the point 
                    Point3Ds resPoints = resLine3D[0];
                    for (Int32 i = 0; i < resPoints.Count; i++)
                    {
                        GeoPoint3D geoPoint = new GeoPoint3D(resPoints[i]);
                        SetGeometry3DStyle(geoPoint);
                        m_SceneControl.Scene.TrackingLayer.Add(geoPoint, "Geometry" + i.ToString());
                    }

                    EndOneMeasure();
                    m_SceneControl.Scene.TrackingLayer.Add(resLine3D, "Geometry");

                    // 添加结果文字
                    // Add a result description
                    text = String.Format("{0}{1}{2}", "总长度： ", Math.Round(Convert.ToDecimal(e.Length), 2), "米");
                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                    {
                        text = String.Format("{0}{1}{2}", "The total length： ", Math.Round(Convert.ToDecimal(e.Length), 2), "Meters");
                    }
                    GeoLine3D line = (geometry as GeoLine3D);
                    textLocation = line[0][line[0].Count - 2];

                    //ClearTextMessageTag();
                    int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTrackingTag);
                    if (index >= 0)
                    {
                        m_SceneControl.Scene.TrackingLayer.Remove(index);
                    }
                    GeoText3D geoText = new GeoText3D(new TextPart3D(text, textLocation));
                    SetResultTextStyle(geoText);

                    m_SceneControl.Scene.TrackingLayer.Add(geoText, "MeasureResult");

                    m_FormMainRibbon.ShowInfo(text);

                    // 计算首尾点高度差
                    // Calulate the head and tall height difference
                    Point3Ds point3Ds = resLine3D[0];
                    double height = point3Ds[point3Ds.Count - 1].Z - point3Ds[0].Z;
                    string message = string.Format("首尾点高度差为:{0}米。", height.ToString("##.00"));
                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                    {
                        message = string.Format("The head and tall height difference is:{0}Meters。", height.ToString("##.00"));
                    }
                    m_FormMainRibbon.ShowInfo(message);
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
            finally
            {
            }
        }

        /// <summary>
        /// 设置添加到TrackingLayer的三维几何对象的风格
        /// Set the style of the 3D geometry to be added to the tracking layer
        /// </summary>
        /// <param name="geometry"></param>
        private void SetGeometry3DStyle(Geometry3D geometry)
        {
            try
            {
                GeoStyle3D style = new GeoStyle3D();

                if (m_SceneControl.Action == Action3D.MeasureAltitude || m_SceneControl.Action == Action3D.MeasureDistance || m_SceneControl.Action == Action3D.MeasureHorizontalDistance)
                {
                    style.AltitudeMode = AltitudeMode.Absolute;
                }
                else
                {
                    style.AltitudeMode = AltitudeMode.ClampToGround;
                }

                style.MarkerSize = 4;
                style.MarkerColor = Color.FromArgb(255, 0, 255);

                style.LineColor = Color.Yellow;
                style.LineWidth = 2;
                style.FillMode = FillMode3D.LineAndFill;
                style.FillForeColor = Color.LightSeaGreen;
                geometry.Style3D = style;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 设置量算结果文本的风格
        /// Set the style of the text of the measure result
        /// </summary>
        /// <param name="text"></param>
        private void SetResultTextStyle(GeoText3D text)
        {
            try
            {
                TextStyle textStyle = new TextStyle
                {
                    ForeColor = Color.White,
                    Outline = true,
                    BackColor = Color.Black,
                    FontHeight = 10
                };
                text.TextStyle = textStyle;
                GeoStyle3D style = new GeoStyle3D();
                if (m_SceneControl.Action == Action3D.MeasureAltitude)
                {
                    style.AltitudeMode = AltitudeMode.Absolute;
                }
                else
                {
                    style.AltitudeMode = AltitudeMode.ClampToGround;
                }
                text.Style3D = style;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 标签中显示当前跟踪量算的结果
        /// Display the result of the measure in the label
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TrackingHandler(object sender, Tracking3DEventArgs e)
        {
            if (m_UnRegistered) return;
            try
            {
                OutputMeasureResult(e);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 开始距离量算
        /// Measure the distance
        /// </summary>
        public void BeginMeasureDistance()
        {
            m_SceneControl.Action = Action3D.MeasureDistance;
        }

        /// <summary>
        /// 开始依地距离量算
        /// Measure the TerrainDistance
        /// </summary>
        public void BeginMeasureTerrainDistance()
        {
            m_SceneControl.Action = Action3D.MeasureTerrainDistance;
        }

        /// <summary>
        /// 开始水平距离量算
        /// Measure the HorizontalDistance
        /// </summary>
        public void BeginMeasureHorizontalDistance()
        {
            m_SceneControl.Action = Action3D.MeasureHorizontalDistance;
        }

        /// <summary>
        /// 开始空间距离量算
        /// Measure the area
        /// </summary>
        public void BeginMeasureArea()
        {
            m_SceneControl.Action = Action3D.MeasureArea;
        }

        /// <summary>
        /// 开始高度量算
        /// Measure the Altitude
        /// </summary>
        public void BeginMeasureAltitude()
        {
            m_SceneControl.Action = Action3D.MeasureAltitude;
        }

        /// <summary>
        /// 清空量算结果
        /// Clear Result
        /// </summary>
        public void ClearResult()
        {
            try
            {
                m_SceneControl.Scene.TrackingLayer.Clear();
                m_SceneControl.Action = Action3D.Pan;
                m_currentGeoText3DMessage = null;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 开始依地面积量算
        /// Measure the TerrainArea
        /// </summary>
        public void BeginMeasureTerrainArea()
        {
            m_SceneControl.Action = Action3D.MeasureTerrainArea;
        }


        // 输出量算结果
        // Output the result
        private void OutputMeasureResult(SuperMap.UI.Tracking3DEventArgs e)
        {
            if (m_SceneControl.Action == Action3D.MeasureDistance || m_SceneControl.Action == Action3D.MeasureTerrainDistance || m_SceneControl.Action == Action3D.MeasureHorizontalDistance)
            {
                if (e.CurrentLength > 0)
                {
                    m_CurLength = e.CurrentLength;
                    Double tempCurLength = m_CurLength;
                    Double tempTotalLength = e.TotalLength;
                    m_StrResult = String.Format("    ", tempCurLength, " " + "米", tempTotalLength, " " + "米");
                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                    {
                        m_StrResult = String.Format("    ", tempCurLength, " " + "Meters", tempTotalLength, " " + "Meters");
                    }
                    OutputMeasureDistance(e);
                }
            }

            if (m_SceneControl.Action == Action3D.MeasureArea || m_SceneControl.Action == Action3D.MeasureTerrainArea)
            {
                Double area = e.TotalArea;
                m_StrResult = String.Format("", area, " " + "米");
                if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                {
                    m_StrResult = String.Format("", area, " " + "Meters");
                }

                if (!Toolkit.IsZero(e.TotalArea))
                {
                    OutputMeasureArea(e);
                }
            }

            if (m_SceneControl.Action == Action3D.MeasureAltitude)
            {
                Double currentHeight = e.CurrentHeight;
                m_StrResult = String.Format("    ", currentHeight, " " + "米");
                if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                {
                    m_StrResult = String.Format("    ", currentHeight, " " + "Meters");
                }
                OutputMeasureAltitude(e);
            }
        }

        private void OutputMeasureArea(SuperMap.UI.Tracking3DEventArgs e)
        {
            try
            {
                Point location = m_SceneControl.PointToClient(Cursor.Position);

                if (m_TempPoint != Point3D.Empty)
                {
                    m_Point3Ds.Remove(m_Point3Ds.Count - 1);
                }
                m_TempPoint = new Point3D(e.X, e.Y, e.Z);
                m_Point3Ds.Add(m_TempPoint);

                GeoRegion3D geoRegion3D = null;
                if (m_Point3Ds.Count >= 3)
                {
                    geoRegion3D = new GeoRegion3D(m_Point3Ds)
                    {
                        Style3D = m_GeoStyle3DTemp.Clone()
                    };

                    location.Offset(30, 30);
                    if (location.X > m_SceneControl.Bounds.Width / 4 * 3)
                    {
                        location.X = m_SceneControl.Bounds.Width / 4 * 3;
                    }
                    if (location.Y > m_SceneControl.Bounds.Height)
                    {
                        location.Y -= 60;
                    }

                    TextPart3D textPart3D = new TextPart3D
                    {
                        AnchorPoint = new Point3D(0, 0, 0),
                        Text = String.Empty
                    };

                    TextStyle style = new TextStyle
                    {
                        ForeColor = Color.White,
                        IsSizeFixed = true,
                        FontHeight = 6,
                        Alignment = TextAlignment.BottomLeft,
                        BackColor = Color.Black,
                        Outline = true
                    };
                    GeoText3D text3d = new GeoText3D(textPart3D, style)
                    {
                        Style3D = new GeoStyle3D()
                    };
                    text3d.Style3D.AltitudeMode = AltitudeMode.Absolute;
                    if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                    {
                        text3d[0].Text = e.TotalArea.ToString("##.00") + "平方米";
                    }
                    else
                    {
                        text3d[0].Text = e.TotalArea.ToString("##.00") + "Square Meters";
                    }
                    if (e.Geometry != null)
                    {
                        text3d[0].X = e.Geometry.InnerPoint.X;
                        text3d[0].Y = e.Geometry.InnerPoint.Y;
                    }
                    else
                    {
                        text3d[0].X = geoRegion3D.InnerPoint.X;
                        text3d[0].Y = geoRegion3D.InnerPoint.Y;
                    }

                    int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTrackingTag);
                    if (index >= 0)
                    {
                        m_SceneControl.Scene.TrackingLayer.Remove(index);
                    }
                    m_SceneControl.Scene.TrackingLayer.Add(text3d, m_messageTrackingTag);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
        }
        private void OutputMeasureDistance(SuperMap.UI.Tracking3DEventArgs e)
        {
            try
            {
                Point location = m_SceneControl.PointToClient(Cursor.Position);

                if (m_TempPoint != Point3D.Empty && m_Point3Ds.Count > 1)
                {
                    m_Point3Ds.Remove(m_Point3Ds.Count - 1);
                }
                m_TempPoint = new Point3D(e.X, e.Y, e.Z);
                m_Point3Ds.Add(m_TempPoint);

                location.Offset(30, 30);
                if (location.X > m_SceneControl.Bounds.Width / 3 * 2)
                {
                    location.X = m_SceneControl.Bounds.Width / 3 * 2;
                }
                if (location.Y > m_SceneControl.Bounds.Height)
                {
                    location.Y -= 60;
                }

                TextPart3D textPart3D = new TextPart3D
                {
                    AnchorPoint = new Point3D(0, 0, 0),
                    Text = String.Empty
                };

                TextStyle style = new TextStyle
                {
                    ForeColor = Color.White,
                    IsSizeFixed = true,
                    FontHeight = 6,
                    Alignment = TextAlignment.BottomLeft,
                    BackColor = Color.Black,
                    Outline = true
                };
                GeoText3D text3d = new GeoText3D(textPart3D, style)
                {
                    Style3D = new GeoStyle3D()
                };
                text3d.Style3D.AltitudeMode = AltitudeMode.Absolute;
                if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                {
                    text3d[0].Text = e.CurrentLength.ToString("##.00") + "米";
                }
                else
                {
                    text3d[0].Text = e.CurrentLength.ToString("##.00") + "Meters";
                }
                Point3D lastPoint = Point3D.Empty;
                if (e.Geometry != null)
                {
                    Point3Ds points = (e.Geometry as GeoLine3D)[0];
                    lastPoint = points[points.Count - 1];
                }
                else
                {
                    lastPoint = m_Point3Ds[0];
                }
                text3d[0].X = (lastPoint.X + e.X) / 2;
                text3d[0].Y = (lastPoint.Y + e.Y) / 2;

                int index = m_SceneControl.Scene.TrackingLayer.IndexOf(m_messageTrackingTag);
                if (index >= 0)
                {
                    m_SceneControl.Scene.TrackingLayer.Remove(index);
                }
                m_SceneControl.Scene.TrackingLayer.Add(text3d, m_messageTrackingTag);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
        }

        private void OutputMeasureAltitude(SuperMap.UI.Tracking3DEventArgs e)
        {
            try
            {
                Point location = m_SceneControl.PointToClient(Cursor.Position);
                location.Offset(30, 30);
                if (location.X > m_SceneControl.Bounds.Width / 5 * 4)
                {
                    location.X = m_SceneControl.Bounds.Width / 5 * 4;
                }
                if (location.Y > m_SceneControl.Bounds.Height)
                {
                    location.Y -= 60;
                }

                GeoText3D text3d = GetGeoText3DMessage();

                text3d.TextStyle.FontHeight = 6;
                text3d.TextStyle.Alignment = TextAlignment.BottomLeft;
                text3d.TextStyle.BackColor = Color.Black;
                text3d.TextStyle.Outline = true;
                text3d.Style3D.AltitudeMode = AltitudeMode.Absolute;

                if (SuperMap.Data.Environment.CurrentCulture == "zh-CN")
                {
                    text3d[0].Text = e.CurrentHeight.ToString("##.00") + "米";
                }
                else
                {
                    text3d[0].Text = e.CurrentHeight.ToString("##.00") + "Meters";
                }

                text3d[0].X = e.X;
                text3d[0].Y = e.Y;
                text3d[0].Z = e.Z + e.CurrentHeight;

                Console.WriteLine(text3d[0].Z);

                text3d.Style3D.AltitudeMode = AltitudeMode.Absolute;

                ClearTextMessageTag();
                m_SceneControl.Scene.TrackingLayer.Add(text3d, m_messageTag);
                m_CurAltitude = e.CurrentHeight;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
        }
    }
}
